package xyz.xiangyushui.subtitleConverter;

import java.util.regex.Matcher;
import java.util.regex.Pattern;
import xyz.xiangyushui.subtitleConverter.exception.InvalidTimePointException;

/**
 * this class represents a time point in subtitle file ,a time point like
 * 00:02:23,123
 * 
 * @author Ivan
 */
public class TimePoint {
	private int hour;
	private byte minute;
	private byte second;
	private String s_msSeperator;
	private int millisecond;

	public TimePoint() {
	}

	public TimePoint(int hour, byte minute, byte second, String smsSeperator, int millisecond) {
		super();
		this.hour = hour;
		this.minute = minute;
		this.second = second;
		this.s_msSeperator = smsSeperator;
		this.millisecond = millisecond;
	}

	/**
	 * construct a TimePoint according to a timeLine string such as 00:12:45,020
	 * in srt or 00:12:23.34 in ass
	 * 
	 * @param timePoint
	 * @throws InvalidTimePointException
	 */
	public TimePoint(String timePoint) throws InvalidTimePointException {
		Matcher m = Pattern.compile("(\\d{1,}):(\\d{2}):(\\d{2})([.,])(\\d{1,})").matcher(timePoint);
		if (!m.matches())
			throw new InvalidTimePointException("invalid time point:" + timePoint);
		try {
			this.hour = toInt(m.group(1));
			this.minute = toByte(m.group(2));
			this.second = toByte(m.group(3));
			this.s_msSeperator = m.group(4);
			this.millisecond = toInt(m.group(5));
		} catch (NumberFormatException e) {
			throw new InvalidTimePointException("invalid time point:" + timePoint);
		}
	}

	/**
	 * increase several seconds and milliseconds remain the same
	 * 
	 * @param second
	 * @return TimePoint
	 */
	public TimePoint increase(int second) {
		secondToTimepoint(this.toSecond() + second);
		return this;
	}

	/**
	 * decrease several seconds and milliseconds remain the sames
	 * 
	 * @param second
	 * @return TimePoint
	 */
	public TimePoint decrease(int second) {
		if (this.toSecond() < second) {
			return this;
		}
		secondToTimepoint(this.toSecond() - second);
		return this;
	}

	/**
	 * convert a timrPoint to string
	 */
	public String toString() {
		return format2digit(hour)+":" + format2digit(minute)+":" + format2digit(second) + s_msSeperator + millisecond;
	}

	/**
	 * convert seconds to timePoint
	 * 
	 * @param second
	 * @return
	 */
	private void secondToTimepoint(int second) {
		this.hour = second / 3600;
		this.minute = (byte) (second % 3600 / 60);
		this.second = (byte) (second % 3600 % 60);
	}

	/**
	 * convert timePoint to seconds
	 * 
	 * @return second
	 */
	private int toSecond() {
		return hour * 3600 + minute * 60 + second;
	}

	private int toInt(String i) throws NumberFormatException {
		return Integer.parseInt(i);
	}

	private byte toByte(String i) {
		return Byte.parseByte(i);
	}

	private String format2digit(int i) {
		return String.format("%02d", i);
	}
}
